﻿using AutoMapper;
using Consul;
using MD5Hash;
using MediatR;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using RBAC_Uthorization.Domain;
using RBAC_Uthorization.Domain.Entity;
using RBAC_Uthorization.Infrstructre.Interface;
using RBAC_Uthorization.Read.API.Application.Command.UserInfoCommand;
using RBAC_Uthorization.Read.API.DTO;
using RBAC_Uthorization.Read.API.DTO.Response;
using RBAC_Uthorization.Read.API.Extensions;
using StackExchange.Redis;
using System.Data;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;

namespace RBAC_Uthorization.Read.API.Application.CommandHandlers.UserInfoHandler
{
    public class userLogincommandHandlers : IRequestHandler<userLogincommand, ApiResult<string>>
    {
        private readonly IUserInfoRepository _userInfoRepository;
        private readonly ILogger<userLogincommandHandlers> _logger;
        private readonly IConfiguration _configuration;
        private readonly IUserRoleRepository _userRoleRepository;
        private readonly IRoleMenuFuncRepository _roleMenuFuncRepository;
        private readonly IRoleMenuRepository _roleMenuRepository;
        private readonly IMenuRepository _menuRepository;
        private readonly IRoleRepository _roleRepository;
        private readonly RedisConnectionService db;

        public userLogincommandHandlers(ILogger<userLogincommandHandlers> logger, IUserInfoRepository userInfoRepository, IConfiguration configuration, IUserRoleRepository userRoleRepository, IRoleMenuFuncRepository roleMenuFuncRepository, IRoleMenuRepository roleMenuRepository, IRoleRepository roleRepository, IMenuRepository menuRepository, RedisConnectionService redis)
        {
            _logger = logger;
            _userInfoRepository = userInfoRepository;
            _configuration = configuration;
            _userRoleRepository = userRoleRepository;
            _roleMenuFuncRepository = roleMenuFuncRepository;
            _roleMenuRepository = roleMenuRepository;
            _roleRepository = roleRepository;
            _menuRepository = menuRepository;
            db = redis;
        }

        public async Task<ApiResult<string>> Handle(userLogincommand request, CancellationToken cancellationToken)
        {
           
            var user = await _userInfoRepository.GetAllAsync();
            var userInfo = user.FirstOrDefault(x => x.login_name == request.username && x.sys_id == request.sys_id);
            if (userInfo == null)
            {
                return new ApiResult<string> { Code = ResultCode.NoContent, Message = "用户不存在" };
            }
            if (userInfo.lock_time > DateTime.UtcNow)
            {
                _logger.LogDebug($"用户id:{userInfo.id},用户名称{userInfo.name}，结束封禁时间：{userInfo.lock_time},IP地址：{request.IpAddress}");
                return new ApiResult<string>
                {
                    Code = ResultCode.Unauthorized,
                    Message = $"账户已被锁定，请在{userInfo.lock_time}后再试",
                };
            }
            if (userInfo.password != request.password.GetMD5())
            {
                var logincount = 5 - userInfo.login_count;
                userInfo.login_count += 1;
                if (userInfo.login_count == 5)
                {
                    userInfo.lock_time = DateTime.UtcNow.AddMinutes(1);
                    userInfo.login_count = 0;
                }
                await _userInfoRepository.UpdateAsync(userInfo);
                return new ApiResult<string> { Code = ResultCode.Unauthorized, Message = $"登录失败，您还可以尝试{logincount}次" };
            }
            if (userInfo.login_flag == 0)
            {
                return new ApiResult<string>
                {
                    Code = ResultCode.Unauthorized,
                    Message = $"账户已被禁止登录",
                };
            }
            // 重置登录次数
            userInfo.login_count = 0;
            userInfo.lock_time = null;
            userInfo.login_ip = request.IpAddress;
            userInfo.login_date = DateTime.UtcNow;
            await _userInfoRepository.UpdateAsync(userInfo);
            var menuss = await _menuRepository.GetAllAsunc(x => x.sys_id == request.sys_id && x.del_flag == 0);
            if (_configuration["Redis:Redisif"] == "1")
            {
                var cachedUser = await db.GetAsync($"user:{userInfo.id}:{userInfo.sys_id}");
                if (cachedUser != null)
                {

                    var roleIdvalue = await db.GetAsync($"user:{userInfo.id}:{userInfo.sys_id}:roleIds");
                    if (roleIdvalue == null)
                    {
                        var userRoles = await _userRoleRepository.GetAllAsunc(x => x.user_id == userInfo.id && x.del_flag == 0);
                        var roless = userRoles.Select(x => x.role_id).ToList();
                      ;
                        await db.SetAsync($"user:{userInfo.id}:{userInfo.sys_id}:roleIds", JsonConvert.SerializeObject(roless));
                    }
                    var menu = await db.GetAsync($"Menu_{request.sys_id}");
                    if (menu == null)
                    {

                        await db.SetAsync($"Menu_{request.sys_id}", JsonConvert.SerializeObject(menuss));
                    }
                    var tokenvalues = CreateTokenString(userInfo.id.ToString(), userInfo.offic_id, userInfo.name, userInfo.avatar, userInfo.sys_id, roleIdvalue);
                    return new ApiResult<string> { Code = ResultCode.Ok, Data = tokenvalues, Message = "登录成功(缓存)" };

                }
            }
            var userRole = await _userRoleRepository.GetAllAsunc(x => x.user_id == userInfo.id && x.del_flag == 0);
            var roleId = userRole.Select(x => x.role_id).ToList();

            var userValue = JsonConvert.SerializeObject(userInfo);


            if (_configuration["Redis:Redisif"] == "1")
            { 
            // 将用户信息存储到 Redis 缓存中
            await db.SetAsync($"user:{userInfo.id}:{userInfo.sys_id}", userValue);
            await db.SetAsync($"user:{userInfo.id}:{userInfo.sys_id}:roleIds",JsonConvert.SerializeObject(roleId));
            await db.SetAsync($"Menu_{request.sys_id}", JsonConvert.SerializeObject(menuss));
            }
            var token = CreateTokenString(userInfo.id.ToString(), userInfo.offic_id, userInfo.name, userInfo.avatar, userInfo.sys_id, string.Join(',', roleId));
            return new ApiResult<string> { Code = ResultCode.Ok, Data = token, Message = "登录成功" };
        }

        private string CreateTokenString(string uid, string offclid, string UserName, string img, string jti, string roleid)
        {
            var claims = new Claim[]
            {
                    new Claim(JwtRegisteredClaimNames.Sub, uid),//用户id
                    new Claim(JwtRegisteredClaimNames.Sid, offclid),//公司id
                    new Claim(JwtRegisteredClaimNames.Jti, jti),//唯一标识系统
                    new Claim(ClaimTypes.GroupSid, roleid),//角色id
                    new Claim(ClaimTypes.Name, UserName),
                    new Claim(ClaimTypes.Uri, img)
            };
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecurityKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: _configuration["Jwt:Issuer"],
                audience: _configuration["Jwt:Audience"],
                claims: claims,
                signingCredentials: creds
            );
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
        //HttpContext.User.FindFirst(ClaimTypes.GroupSid)?.Value //角色id
        //HttpContext.User.FindFirst(JwtRegisteredClaimNames.Jti)?.Value //唯一标识系统
        //HttpContext.User.FindFirst(JwtRegisteredClaimNames.Sid)?.Value //公司id
        //HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value //用户id
        //HttpContext.User.FindFirst(ClaimTypes.Name)?.Value //用户名
        //HttpContext.User.FindFirst(ClaimTypes.Uri)?.Value //头像
    }
}
